package com.ngant.maskbitmapexample;

import android.content.Context;
import android.graphics.AvoidXfermode;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.ColorMatrixColorFilter;
import android.graphics.Paint;
import android.graphics.PorterDuff.Mode;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.RectF;

public class RoundedCorner {

	public static Bitmap getRoundedCornerBitmap(Bitmap bitmap) 
	{
	    Bitmap output = Bitmap.createBitmap(bitmap.getWidth(),
	        bitmap.getHeight(), Config.ARGB_8888);
	    
	    Canvas canvas = new Canvas(output);

	    final int color = 0xff424242;
	    final Paint paint = new Paint();
	    final Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());
	    final RectF rectF = new RectF(rect);
	    final float roundPx = 30;

	    paint.setAntiAlias(true);
	    canvas.drawARGB(0, 0, 0, 0);
	    paint.setColor(color);
	    canvas.drawRoundRect(rectF, roundPx, roundPx, paint);

	    paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
	    canvas.drawBitmap(bitmap, rect, rect, paint);

	    return output;
	  }
	
	public static Bitmap getRoundedCornerBitmap(Context context, Bitmap input, int pixels , int w , int h , boolean squareTL, boolean squareTR, boolean squareBL, boolean squareBR  ) {

	    Bitmap output = Bitmap.createBitmap(w, h, Config.ARGB_8888);
	    Canvas canvas = new Canvas(output);
	    final float densityMultiplier = context.getResources().getDisplayMetrics().density;

	    final int color = 0xff424242;
	    final Paint paint = new Paint();
	    final Rect rect = new Rect(0, 0, w, h);
	    final RectF rectF = new RectF(rect);

	    //make sure that our rounded corner is scaled appropriately
	    final float roundPx = pixels*densityMultiplier;

	    paint.setAntiAlias(true);
	    canvas.drawARGB(0, 0, 0, 0);
	    paint.setColor(color);
	    canvas.drawRoundRect(rectF, roundPx, roundPx, paint);


	    //draw rectangles over the corners we want to be square
	    if (squareTL ){
	        canvas.drawRect(0, 0, w/2, h/2, paint);
	    }
	    if (squareTR ){
	        canvas.drawRect(w/2, 0, w, h/2, paint);
	    }
	    if (squareBL ){
	        canvas.drawRect(0, h/2, w/2, h, paint);
	    }
	    if (squareBR ){
	        canvas.drawRect(w/2, h/2, w, h, paint);
	    }

	    paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
	    canvas.drawBitmap(input, 0,0, paint);

	    return output;
	}

	
	/**
	 * Use this method to scale a bitmap and give it specific rounded corners.
	 * @param context Context object used to ascertain display density.
	 * @param bitmap The original bitmap that will be scaled and have rounded corners applied to it.
	 * @param upperLeft Corner radius for upper left.
	 * @param upperRight Corner radius for upper right.
	 * @param lowerRight Corner radius for lower right.
	 * @param lowerLeft Corner radius for lower left.
	 * @param endWidth Width to which to scale original bitmap.
	 * @param endHeight Height to which to scale original bitmap.
	 * @return Scaled bitmap with rounded corners.
	 */
	public static Bitmap getRoundedCornerBitmap(Context context, Bitmap bitmap, float upperLeft,
	        float upperRight, float lowerRight, float lowerLeft, int endWidth,
	        int endHeight) {
	    float densityMultiplier = context.getResources().getDisplayMetrics().density;

	    // scale incoming bitmap to appropriate px size given arguments and display dpi
	    bitmap = Bitmap.createScaledBitmap(bitmap, 
	            Math.round(endWidth * densityMultiplier),
	            Math.round(endHeight * densityMultiplier), true);

	    // create empty bitmap for drawing
	    Bitmap output = Bitmap.createBitmap(
	            Math.round(endWidth * densityMultiplier),
	            Math.round(endHeight * densityMultiplier), Config.ARGB_8888);

	    // get canvas for empty bitmap
	    Canvas canvas = new Canvas(output);
	    int width = canvas.getWidth();
	    int height = canvas.getHeight();

	    // scale the rounded corners appropriately given dpi
	    upperLeft *= densityMultiplier;
	    upperRight *= densityMultiplier;
	    lowerRight *= densityMultiplier;
	    lowerLeft *= densityMultiplier;

	    Paint paint = new Paint();
	    paint.setAntiAlias(true);
	    paint.setColor(Color.WHITE);

	    // fill the canvas with transparency
	    canvas.drawARGB(0, 0, 0, 0);

	    // draw the rounded corners around the image rect. clockwise, starting in upper left.
	    canvas.drawCircle(upperLeft, upperLeft, upperLeft, paint);
	    canvas.drawCircle(width - upperRight, upperRight, upperRight, paint);
	    canvas.drawCircle(width - lowerRight, height - lowerRight, lowerRight, paint);
	    canvas.drawCircle(lowerLeft, height - lowerLeft, lowerLeft, paint);

	    // fill in all the gaps between circles. clockwise, starting at top.
	    RectF rectT = new RectF(upperLeft, 0, width - upperRight, height / 2);
	    RectF rectR = new RectF(width / 2, upperRight, width, height - lowerRight);
	    RectF rectB = new RectF(lowerLeft, height / 2, width - lowerRight, height);
	    RectF rectL = new RectF(0, upperLeft, width / 2, height - lowerLeft);

	    canvas.drawRect(rectT, paint);
	    canvas.drawRect(rectR, paint);
	    canvas.drawRect(rectB, paint);
	    canvas.drawRect(rectL, paint);

	    // set up the rect for the image
	    Rect imageRect = new Rect(0, 0, width, height);

	    // set up paint object such that it only paints on Color.WHITE
	    paint.setXfermode(new AvoidXfermode(Color.WHITE, 255, AvoidXfermode.Mode.TARGET));

	    // draw resized bitmap onto imageRect in canvas, using paint as configured above
	    canvas.drawBitmap(bitmap, imageRect, imageRect, paint);

	    return output;
	}
	
	/**
	 * Mask a (typically opaque) source bitmap according to the intensity of its pixels.
	 * 
	 * @param source the image to be 
	 * @param color a fixed color used to render the source image,
	 *        or zero use the source colors 
	 * @param invert true if lighter pixels are more transparent,
	 *        false if the converse is true
	 * @param target optional bitmap in which the result will be stored,
	 *        passing in null will generate an ARGB bitmap of the same dimensions
	 * @return a bitmap containing the masked source
	 */

	public static Bitmap toTransparency(final Bitmap source, final int color, boolean invert, Bitmap target) {
	    //cache the values we know we will need
	    final int srcW = source.getWidth();
	    final int srcH = source.getHeight();

	    //generate the color matrix coefficients 
	    final float[] coefficients;
	    if (color == 0) {
	        final float m = invert ? -0.333333f : 0.333333f;
	        final float ac = invert ? 256f : 0f;
	        coefficients = new float[] {
	            1, 0, 0, 0, 0,
	            0, 1, 0, 0, 0,
	            0, 0, 1, 0, 0,
	            0, 0, 0, 1, 0,
	            m, m, m, 0, ac,
	        };
	    } else {
	        //(these rgb assignments could be tidied away)
	        final int a = (color >> 24) & 0xff;
	        final int r = (color >> 16) & 0xff;
	        final int g = (color >>  8) & 0xff;
	        final int b = (color      ) & 0xff;
	        final float m = a/255f * (invert ? -0.333333f : 0.333333f);
	        final float ac = a * (invert ? 1f : 0f);
	        coefficients = new float[] {
	            0, 0, 0, 0, r,
	            0, 0, 0, 0, g,
	            0, 0, 0, 0, b,
	            m, m, m, 0, ac,
	        };
	    }

	    //create a suitable target if none specified
	    final boolean sameSize;
	    if (target == null) {
	        target = Bitmap.createBitmap(srcW, srcH, Bitmap.Config.ARGB_8888);
	        sameSize = true;
	    } else {
	        sameSize = target.getWidth() == srcW && target.getHeight() == srcH;
	    }

	    //prepare our canvas and paint
	    //(everything here could be cached in some way)
	    final Canvas canvas = new Canvas(target);
	    final Paint paint = new Paint();
	    paint.setFilterBitmap(true);
	    paint.setXfermode(new PorterDuffXfermode(Mode.SRC));
	    paint.setColorFilter(new ColorMatrixColorFilter(coefficients));

	    //do conversion of the source bitmap
	    if (sameSize) {
	        canvas.drawBitmap(source, 0, 0, paint);
	    } else {
	        Rect src = new Rect(0, 0, srcW, srcH);
	        Rect dst = new Rect(0, 0, target.getWidth(), target.getHeight());
	        canvas.drawBitmap(source, src, dst, paint);
	    }

	    //return the result
	    return target;
	}

}
